package com.df.common.utils;


import com.df.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public final class MySocket {
     byte STX = 0x02;
     byte SOU = 0x01;
     byte ETX = 0x03;
     public Socket socket = null;

    // 心跳定时发送时间(s)
    public  final int _sleepTime = 36;
    // 业务包间隔发送时间(s) 1-N秒
    public  final int _intervalTime = 10;
    // socket连接超时时间(s)
    public  final int _connectTimeOut = 2;
    // socket 回复超时时间(s)
    public  final int _receiveTimeOut = 10;
    public  final SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
    //    String hostName="192.168.1.198";
     String hostName = "192.168.0.128";
    //    int port=58062;
     int port = 58064;
     int timeCounter = 0;


     public void Close() throws IOException {
         socket.close();
     }

    public  boolean Reconnet() {
        try {
            Socket _s = socket;
            socket = new Socket();

            if ((_s != null) && (!_s.isClosed())) {
                _s.close();
            }
            SocketAddress socketAddress = new InetSocketAddress(InetAddress.getByName(hostName), port);
            socket.connect(socketAddress, _connectTimeOut * 1000);
            socket.setSoTimeout(_receiveTimeOut * 1000);
            timeCounter = _sleepTime;
            timeCounter = 3;
            System.out.print("Connect:" + hostName + ":" + port + "\n");
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, hostName + " : " + port + "\n" + e.getMessage());
            return false;
        }
    }

    String header = new String("");
    String messageClass = new String("");
    static  String transactionID = new String("");
    String reply = new String("");
    String location = new String("");
    String routeID = new String("1001");
    String routeName = new String("LINE1");
    String equipmentID = new String("1000");
    String zoneID = new String("1");
    String zonePos = new String("1");
    String zoneName = new String("1");
    String laneNo = new String("1");
    String controllerGuid = new String("");
    public static String equipmentName = "S01-L10-MPI-M1";
    static SimpleDateFormat t = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    //Gp12
    public  String Send_501(String recieve_sn,String equipment,String pcbSide){

        String xmlMsg = "<message>" +
                "<header messageClass=\"501\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"1\" >" +
                "<location routeID=\"1000\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1000\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"1\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                "<pcb barcode=\"" + recieve_sn + "\" modelCode=\"1\" serialNo=\"1\" pcbSide=\""+pcbSide+"\"  />" +
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
        String errorCode= GetElement(recvMsg, "errorCode");
        String errorText = GetElement(recvMsg, "errorText");
        return errorCode+","+errorText;
    }

    public  String Send_501Gp12(String recieve_sn,String equipment,String pcbSide){

        String xmlMsg = "<message>" +
                "<header messageClass=\"501\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"1\" >" +
                "<location routeID=\"1000\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1000\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"1\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                "<pcb barcode=\"" + recieve_sn + "\" modelCode=\"1\" serialNo=\"1\" pcbSide=\""+pcbSide+"\" procedureNumber=\"A0202\" />" +
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
        String errorCode= GetElement(recvMsg, "errorCode");
        String errorText = GetElement(recvMsg, "errorText");
        return errorCode+","+errorText;
    }

    public  String Send_5506(String sn,String label,String pcbSide,String equipment,String number){

        String xmlMsg = "<message>" +
                "<header messageClass=\"5506\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"1\" >" +
                "<location routeID=\"1000\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1000\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"1\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                "<panelcomp type=\"new\">\n"+
                "<main>\n"+
                "<panel state=\"0\" pcbID=\""+sn+"\" productName=\""+number+"\" productSide=\""+pcbSide+
                "\" timestamp=\""+t.format(new Date())+"\"/>\n"+
                "</main>\n"+
                "<label>\n"+
                "<panel state=\"0\" pcbID=\""+label+"\" productName=\""+number+"\" productSide=\""+pcbSide+
                "\" timestamp=\""+t.format(new Date())+"\"/>\n"+
                "</label>\n"+
                "</panelcomp>"+
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
        String errorCode= GetElement(recvMsg, "errorCode");
        String errorText = GetElement(recvMsg, "errorText");
        return errorCode+","+errorText;
    }

    public  String Send_550(String recieve_sn, String equipment){

        String xmlMsg = "<message>" +
                "<header messageClass=\"550\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"1\" >" +
                "<location routeID=\"1000\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1000\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"1\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                // procedureNumber="A0202"
                "<panel timestamp=\"" + t.format(new Date()) + "\" productSide=\"2\" repairType=\"0\" productName=\"test\" pcbID=\"" + recieve_sn + "\" state=\"0\">"+
//                "<subPanel state=\"0\" pos=\\\"\" + i + \"\\\"/>"+
                "</panel>"+
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
        String errorCode= GetElement(recvMsg, "errorCode");
        String errorText = GetElement(recvMsg, "errorText");
       return errorCode+","+errorText;
    }

    public  String Send_550Gp12(String recieve_sn, String equipment){

        String xmlMsg = "<message>" +
                "<header messageClass=\"550\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"1\" >" +
                "<location routeID=\"1000\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1000\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"1\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                // procedureNumber="A0202"
                "<panel timestamp=\"" + t.format(new Date()) + "\" productSide=\"2\" repairType=\"0\" productName=\"test\" pcbID=\"" + recieve_sn + "\" state=\"0\" procedureNumber=\"A0202\">"+
//                "<subPanel state=\"0\" pos=\\\"\" + i + \"\\\"/>"+
                "</panel>"+
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
        String errorCode= GetElement(recvMsg, "errorCode");
        String errorText = GetElement(recvMsg, "errorText");
        return errorCode+","+errorText;
    }


    public  List<String> Send_572(String recieve_sn, String equipment){

        String xmlMsg = "<message>" +
                "<header messageClass=\"572\" transactionID=\"" + equipment + "_" + t.format(new Date()) + "\" reply=\"0\" >" +
                "<location routeID=\"1001\" routeName=\"SMT-1\" equipmentID=\"1000\" equipmentName=\"" + equipment + "\" zoneID=\"1001\" zonePos=\"1\" zoneName=\"" + equipment + "\" laneNo=\"0\" controllerGuid=\"\" />" +
                "</header>" +
                "<body>" +
                "<pallet ID=\""+recieve_sn+"\">"+
                "</pallet>"+
                "</body>" +
                "</message>";
        System.out.println(xmlMsg);
        xmlMsg = DealXMLString(xmlMsg);
        String recvMsg = SendMsg(xmlMsg);
       String errorCode= GetElement(recvMsg, "errorCode");
       String errorText = GetElement(recvMsg, "errorText");
        List<String> list =new ArrayList<>();
        if(errorCode.equals("0")){
            int beginIndex = recvMsg.lastIndexOf("<body>" )-1;
            int endIndex = recvMsg.lastIndexOf("</body>")+7;
            String respXML = StringUtils.substring(recvMsg, beginIndex, endIndex);
             list = respXML(respXML);
        }

        return list;
    }


    public  String SendMsg(String xmlMsg){
        String errorCode=null,errorText=null;
        Reconnet();
        OutputStream os;
        InputStream in;
        String recvMsg = null;
        try {
            if(!socket.isClosed()){
                in = socket.getInputStream();
                os = socket.getOutputStream();
                os.write(STX);// HEAD
                os.write(xmlMsg.getBytes());
                os.write(SOU);// CONTENT
                os.write(xmlMsg.getBytes());
                os.write(ETX); // Delimit...
                os.flush();
                byte[] buf = new byte[9999];
                int recvLen = in.read(buf);
                recvMsg = new String(buf, 0, recvLen, "UTF-8");
                recvMsg = analyseMSG(buf);
                System.out.println(recvMsg);


                os.close();
                in.close();
                socket.close();
                Close();
            }
        }catch (Exception exception){
            exception.printStackTrace();
            log.error(exception.getMessage());
            throw new BusinessException("1,"+exception.getMessage());

        }

        return recvMsg ;
    }

    public static List<String> respXML(String respXML) {
        Document respDoc = null;
        List<String> pcb =new ArrayList<>();
        try {
            respDoc = DocumentHelper.parseText(respXML);
            Element rootElement = respDoc.getRootElement();//获取根节点元素 response
            Element msgInfoListEle = rootElement.element("pallet");// 获取数组节点 msgInfoList
            List<Element> fileList = msgInfoListEle.elements("pcb");
            for (Element file : fileList) {
                //获取各节点对象
                System.out.println(file.attributeValue("sn"));
                pcb.add(file.attributeValue("sn"));
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
        return  pcb;
    }

    public static String GetElement(String Msg, String ElementName) {
        String ElementValue = new String();
        int beginIndex = 0, endIndex = 0;
        beginIndex = Msg.lastIndexOf(ElementName + "=\"") + ElementName.length() + 2;
        endIndex = Msg.indexOf("\"", beginIndex);
//    	System.out.print(Msg+"\n"+ElementName+"\n"+beginIndex+"\n"+endIndex+"\n");
        ElementValue = Msg.substring(beginIndex, endIndex);
        return ElementValue;
    }


    public  String analyseMSG(byte[] MSG) {
        String str, len;
        str = new String("Error");
        len = new String();
        byte[] msg = MSG;
        int intSTX = 0, intSOU = 0, intETX = 0;
        try {
            for (int i = 0; i < msg.length; i++) {
                if (msg[i] == STX) {
                    intSTX = i;
                } else if (msg[i] == SOU) {
                    intSOU = i;
                    len = new String(msg, intSTX + 1, (intSOU - intSTX - 1), "UTF-8");
                } else if (msg[i] == ETX) {
                    intETX = i;
                    if (len.equals("" + (intETX - intSOU - 1))) {
                        str = new String(msg, intSOU + 1, (intETX - intSOU - 1), "UTF-8");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return str;
    }


    public static String DealXMLString(String msg) {// XML 修正 去除 & < > ' "
        msg = msg.replaceAll("&lt;", "<");
        msg = msg.replaceAll("&gt;", ">");
        msg = msg.replaceAll("&amp;", "&");
        msg = msg.replaceAll("&apos;", "\'");
        msg = msg.replaceAll("&quot;", "\"");

        msg.replaceAll("<", "&lt;");
        msg.replaceAll(">", "&gt;");
        msg.replaceAll("\'", "&apos;");
        msg.replaceAll("\"", "&quot;");
        msg = msg.replaceAll("&", "&amp;");
        return msg;
    }

    public String GetHeaderData() {
        header = "<header messageClass=\"" + messageClass + "\" transactionID=\"" + GetTransactionIDData()
                + "\" reply=\"" + reply + "\">\n" + GetLocationData() + "</header>\n";
        return header;
    }

    public String GetTransactionIDData() {
        SimpleDateFormat t = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        transactionID = "" + equipmentName + "_" + t.format(new Date());
        return transactionID;
    }

    public String GetLocationData() {
        location = "<location routeID=\"" + routeID + "\" routeName=\"" + routeName + "\" equipmentID=\"" + equipmentID
                + "\"" + " equipmentName=\"" + equipmentName + "\" zoneID=\"" + zoneID + "\" zonePos=\"" + zonePos
                + "\"" + " zoneName=\"" + zoneName + "\" laneNo=\"" + laneNo + "\" controllerGuid=\"" + controllerGuid
                + "\"" + " />\n";
        return location;
    }

}
